import { defineStore } from 'pinia'
import { ref, computed } from 'vue'
import type { DictItemResponse } from '@/api/system/dict'
import { loadPreloadDicts } from '@/config/dicts'

type DictValue = string | number | boolean

// 与后端返回结构保持一致（直接使用后端返回类型）
export type BackendDictItem = DictItemResponse
export type DictPayload = Record<string, BackendDictItem[]>

export const useDictStore = defineStore(
  'dictStore',
  () => {
    const dicts = ref<DictPayload>({})
    const loaded = ref(false)
    const lastLoadedAt = ref<Record<string, number>>({})

    const getLoaded = computed(() => loaded.value)
    const getAll = computed(() => dicts.value)

    const getDict = (type: string): BackendDictItem[] => dicts.value[type] || []
    // 生成用于组件的 options：label 使用 dict_key，value 使用 dict_value
    const getOptions = (
      type: string
    ): Array<{ label: string; value: DictValue }> =>
      getDict(type).map(({ dict_key, dict_value }) => ({ label: dict_value, value: dict_key }))
    // 根据字典值获取显示文案（dict_key）
    const getLabel = (type: string, value: DictValue): string =>
      getDict(type).find((item) => item.dict_value === value)?.dict_key ?? ''
    // 根据字典值获取完整字典项
    const getItem = (type: string, value: DictValue): BackendDictItem | undefined =>
      getDict(type).find((item) => item.dict_value === value)

    const setDicts = (payload: DictPayload) => {
      dicts.value = payload || {}
      loaded.value = true
      const now = Date.now()
      Object.keys(dicts.value).forEach((k) => (lastLoadedAt.value[k] = now))
    }

    const mergeDicts = (payload: DictPayload) => {
      const merged: DictPayload = { ...dicts.value }
      Object.keys(payload || {}).forEach((key) => {
        merged[key] = payload[key]
        lastLoadedAt.value[key] = Date.now()
      })
      dicts.value = merged
      loaded.value = true
    }

    const clear = () => {
      dicts.value = {}
      loaded.value = false
      lastLoadedAt.value = {}
    }

    const init = (payload?: DictPayload) => {
      if (loaded.value) return
      if (payload) setDicts(payload)
    }

    const getLastLoadedAt = (type?: string): number | Record<string, number> => {
      if (type) return lastLoadedAt.value[type] || 0
      return lastLoadedAt.value
    }

    const needsRefresh = (type: string, ttlMs = 10 * 60 * 1000): boolean => {
      const ts = lastLoadedAt.value[type] || 0
      return !dicts.value[type] || Date.now() - ts > ttlMs
    }

    const ensure = async (
      types?: string[],
      options?: { ttlMs?: number; force?: boolean }
    ): Promise<void> => {
      const ttl = options?.ttlMs ?? 10 * 60 * 1000
      const force = !!options?.force
      const typeList = Array.isArray(types) && types.length ? types : Object.keys(dicts.value)
      const need = typeList.filter((t) => force || needsRefresh(t, ttl))
      if (!need.length) return
      const payload = await loadPreloadDicts(need)
      mergeDicts(payload)
    }

    return {
      dicts,
      loaded,
      lastLoadedAt,
      getLoaded,
      getAll,
      getDict,
      getOptions,
      getLabel,
      getItem,
      setDicts,
      mergeDicts,
      clear,
      init,
      getLastLoadedAt,
      needsRefresh,
      ensure
    }
  },
  {
    persist: {
      key: 'dict',
      storage: localStorage
    }
  }
)